Skip to content

1.1 SwiftUI Essentials(Landmarks)创建并合并视图

Creating and Combining Views — SwiftUI Tutorials | Apple Developer Documentation

创建新项目并使用cavans

新建项目

ContentView.swift 文件内容如下:

swift
import SwiftUI

struct ContentView: View {
	var body: some View {
		Text("Hello, world!")	
	}
}

struct ContentView_Previews: PreviewProvider {
	static var previews: some View {	
		ContentView()	
	}
}
import SwiftUI

struct ContentView: View {
	var body: some View {
		Text("Hello, world!")	
	}
}

struct ContentView_Previews: PreviewProvider {
	static var previews: some View {	
		ContentView()	
	}
}

默认情况下,SwiftUI视图文件声明两个结构体。

  • 第一个结构符合View协议,描述了视图的内容和布局。
  • 第二个结构声明该视图的预览。

定制TextView

您可以通过更改代码来自定义视图的显示,或者使用检查器(inspector)来发现可用的内容并辅助编写代码。

如何使用inspector

  1. 编辑区,command+左键, 点击组件
  2. 选择: Show SwiftUI Inspector

Show SwiftUI Inspector|300

可以将Text字体改成Title:效果将会展示系统字体,并且它会正确响应用户手机设计的字体大小和设置。

|300

modifiers

要自定义SwiftUI视图,可以调用称被为modifiers的方法。modifiers包裹视图以更改其显示或其他属性。每个modifier返回new view,因此可以使用链式语法。

swift
struct ContentView: View {
	var body: some View {
		VStack {
			Text("Turtle Rock")
			.font(.title)
			.foregroundColor(.cyan)
		}
	}
}
struct ContentView: View {
	var body: some View {
		VStack {
			Text("Turtle Rock")
			.font(.title)
			.foregroundColor(.cyan)
		}
	}
}

使用Stacks组合视图

在上面的操作中,我们增加了标题,现在看看如何增加一行详情:展示公园名称和所在州。

当创建SwiftUI视图时,您在视图的body属性中描述其内容、布局和行为;但是,body属性只返回一个视图。为了解决这个问题,我们可以将多个视图组合并嵌入到stack中,stack将视图以horizontally、vertically 或者 back-to-front的方式组合在一起。

将视图嵌入VStack:

|500

增加一个text组件:

|500

修改VStack的alignment为.leading,将文字改为了左对齐:

swift
struct ContentView: View {

	var body: some View {
		VStack(alignment: .leading) {		
			Text("Turtle Rock")			
			.font(.title)		
			.foregroundColor(.cyan)
			
			Text("Joshua Tree National Park")
			.font(.subheadline)		
		}	
	}
}
struct ContentView: View {

	var body: some View {
		VStack(alignment: .leading) {		
			Text("Turtle Rock")			
			.font(.title)		
			.foregroundColor(.cyan)
			
			Text("Joshua Tree National Park")
			.font(.subheadline)		
		}	
	}
}

增加展示公园所在的州:

  1. 先将公园名称控件嵌入HStack
  2. 增加text展示州
  3. 使用spacer撑开中间空间

关于Spacer():

  • Spacer会自动撑开以便其所在的视图使用其父视图中的全部空间,而不仅仅是由其内容定义的大小

使用padding增加默认间距,将视图展示得更美观一些:

定制Image View

前置工作:

  1. 在工程Assets里面增加一张图片,名称为 turtlerock@2x.jpg
  2. 新建一个Swiftui文件,名称为CircleImage.swift

使用clipShape修饰器可以将图片切成我们需要的形状:

|600

创建另一个带有灰色描边的圆,然后将其添加为图片的overlay,为图像提供边框。

|600

使用shadow增加阴影:

swift
struct CircleImage: View {
    var body: some View {
        Image("turtlerock")
            .clipShape(Circle())
            .overlay {
                Circle().stroke(.red, lineWidth: 5)
            }
            // add shadow
            .shadow(radius: 7)
    }
}
struct CircleImage: View {
    var body: some View {
        Image("turtlerock")
            .clipShape(Circle())
            .overlay {
                Circle().stroke(.red, lineWidth: 5)
            }
            // add shadow
            .shadow(radius: 7)
    }
}

在其他框架中使用SwiftUI

接下来,您将创建一个以给定坐标为中心的贴图。您可以使用MapKit中的Map视图来呈现地图。

swift
import SwiftUI

import MapKit

struct MapView: View {

// 创建保存地图区域信息的私有状态变量。
// 你可以使用@State属性来修饰数据源,这样你可以从多个视图中修改数据。 当数据源改变SwiftUI会根据值的变化动态更新依赖该值的视图

	@State
	private var region = MKCoordinateRegion(
	center: CLLocationCoordinate2D(latitude: 34.011_286, longitude: -116.166_868),
	span: MKCoordinateSpan(latitudeDelta: 0.2, longitudeDelta: 0.2)
	)

	var body: some View {	
		// 通过给状态变量加上前缀$,传递了一个绑定,就像是对底层值的引用。当用户与地图交互时,地图更新区域值以匹配用户界面中当前可见的地图部分。
		// Binding<MKCoordinateRegion>
		Map(coordinateRegion: $region)		
	}	
}


struct MapView_Previews: PreviewProvider {
	static var previews: some View {	
		MapView()	
	}
}
import SwiftUI

import MapKit

struct MapView: View {

// 创建保存地图区域信息的私有状态变量。
// 你可以使用@State属性来修饰数据源,这样你可以从多个视图中修改数据。 当数据源改变SwiftUI会根据值的变化动态更新依赖该值的视图

	@State
	private var region = MKCoordinateRegion(
	center: CLLocationCoordinate2D(latitude: 34.011_286, longitude: -116.166_868),
	span: MKCoordinateSpan(latitudeDelta: 0.2, longitudeDelta: 0.2)
	)

	var body: some View {	
		// 通过给状态变量加上前缀$,传递了一个绑定,就像是对底层值的引用。当用户与地图交互时,地图更新区域值以匹配用户界面中当前可见的地图部分。
		// Binding<MKCoordinateRegion>
		Map(coordinateRegion: $region)		
	}	
}


struct MapView_Previews: PreviewProvider {
	static var previews: some View {	
		MapView()	
	}
}

编写详情视图

接下来实现将MapView、Image View集成到Content.swift页面里面。

MapView:

  • 如果仅指定height参数,则视图将自动调整大小为其内容的宽度(VStack中)。在这种情况下,MapView将展开以填充可用空间。

如果要忽略安全区域,可以使用ignoresSafeArea

swift
MapView()
.ignoresSafeArea(edges: .top)
.frame(height: 300)
MapView()
.ignoresSafeArea(edges: .top)
.frame(height: 300)